package com.bugbuff.sso.service;

import cn.hutool.core.util.ObjectUtil;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.baomidou.mybatisplus.core.assist.ISqlRunner;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bugbuff.common.mapper.UserMapper;
import com.bugbuff.common.pojo.User;
import com.bugbuff.common.vo.ErrorResult;
import com.bugbuff.dubbo.server.pojo.FrozenUser;
import com.bugbuff.sso.config.AliyunSMSConfig;
import com.bugbuff.sso.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class SmsService {

    @Autowired
    private AliyunSMSConfig aliyunSMSConfig;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private UserMapper userMapper;

    /**
     * 发送短信验证码
     *
     * @param mobile
     * @return
     */
    public String sendSms(String mobile) {
        DefaultProfile profile = DefaultProfile.getProfile(this.aliyunSMSConfig.getRegionId(),
                this.aliyunSMSConfig.getAccessKeyId(), this.aliyunSMSConfig.getAccessKeySecret());
        IAcsClient client = new DefaultAcsClient(profile);

        String code = RandomUtils.nextInt(100000, 999999) + "";

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain(this.aliyunSMSConfig.getDomain());
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", this.aliyunSMSConfig.getRegionId());
        request.putQueryParameter("PhoneNumbers", mobile); //目标手机号
        request.putQueryParameter("SignName", this.aliyunSMSConfig.getSignName()); //签名名称
        request.putQueryParameter("TemplateCode", this.aliyunSMSConfig.getTemplateCode()); //短信模板code
        request.putQueryParameter("TemplateParam", "{\"code\":\"" + code + "\"}");//模板中变量替换
        try {
            CommonResponse response = client.getCommonResponse(request);
            String data = response.getData();
            if (StringUtils.contains(data, "\"Message\":\"OK\"")) {
                return code;
            }
            log.info("发送短信验证码失败~ data = " + data);
        } catch (Exception e) {
            log.error("发送短信验证码失败~ mobile = " + mobile, e);
        }
        return null;
    }

    /**
     * 发送短信验证码
     * 实现：发送完成短信验证码后，需要将验证码保存到redis中
     *
     * @param phone
     * @return
     */
    public ErrorResult sendCheckCode(String phone) {

//        查看该用户是否被冻结登录
        if (checkStatus(phone))
            return ErrorResult.builder().errCode("000022").errMessage("您已被冻结登录！").build();

        String redisKey = "CHECK_CODE_" + phone;

        //先判断该手机号发送的验证码是否还未失效
        if (this.redisTemplate.hasKey(redisKey)) {
            String msg = "上一次发送的验证码还未失效！";
            return ErrorResult.builder().errCode("000001").errMessage(msg).build();
        }

//        String code = this.sendSms(phone);
        String code = "123456";
        log.info("code的值为：{}", code);

        if (StringUtils.isEmpty(code)) {
            String msg = "发送短信验证码失败！";
            return ErrorResult.builder().errCode("000000").errMessage(msg).build();
        }

        //短信发送成功，将验证码保存到redis中，有效期为5分钟
        this.redisTemplate.opsForValue().set(redisKey, code, Duration.ofMinutes(5));

        return null;
    }

    private boolean checkStatus(String phone) {
        //        3、校验手机号，查询数据库
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>();
        wrapper.eq(User::getMobile, phone);
        User user = userMapper.selectOne(wrapper);

        if (user == null)
            return false;

        String frozenUserRedisKey = "FROZEN_USER_" + user.getId();
        if (redisTemplate.opsForHash().hasKey(frozenUserRedisKey, "1") || isPermanentFrozen(user.getId()))
            return true;

        return false;
    }

    /**
     * 在芒果中查看是否是永久封禁的，如果是，存入redis中7天，否则返回FALSE
     *
     * @param id
     * @return
     */
    private boolean isPermanentFrozen(Long id) {
        Query query = Query.query(Criteria.where("userId").is(id)).with(Sort.by(Sort.Order.desc("created")));
        List<FrozenUser> frozenUserList = mongoTemplate.find(query, FrozenUser.class);
        if (!ObjectUtil.isNotEmpty(frozenUserList))
            return false;

        FrozenUser frozenUser = frozenUserList.get(0);
        if ("1".equals(frozenUser.getUserStatus()))
            return false;

        if (frozenUser.getFreezingTime() == 3) {
            String redisKey = "FROZEN_USER_" + frozenUser.getUserId();
            String hashKey = String.valueOf(frozenUser.getFreezingRange());
            String hashValue = String.valueOf(frozenUser.getFreezingTime());
            if (redisTemplate.hasKey(redisKey))
                redisTemplate.delete(redisKey);
            redisTemplate.opsForHash().put(redisKey, hashKey, hashValue);
            redisTemplate.expire(redisKey, 7, TimeUnit.DAYS);
            return true;
        }
        return false;
    }

}
